//Copyright (c) 2013 Tilo Szepan, Immo Wache
//Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
//documentation files (the "Software"), to deal in the Software without restriction, including without limitation
//the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
//and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

//The above copyright notice and this permission notice shall be included in all copies or substantial portions 
//of the Software.

//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
//TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
//THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
//CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
//DEALINGS IN THE SOFTWARE.

using System;
using System.Text;
using System.Collections.Generic;
using System.Collections.Specialized;
using Gtk;
using Gdk;
using System.IO;
using MonoMobile.Dialogs.Remote.Discovery;

namespace DuinoClient
{
	public class ServerSelect : Gtk.Window
	{
		UsidClient uclient;
		ListStore lstore;
		TreeView tview;
		Button btn_apply;
		MainWindow _main;

		public ServerSelect (MainWindow main) : 
				base(Gtk.WindowType.Toplevel)
		{
			_main = main;
			this.Build ();
            uclient = new UsidClient();
            uclient.EnableBroadcast = true;
			uclient.DataReceived += DataReceived;
			uclient.Start();
			uclient.SendTo("255.255.255.255", 8221, new byte[] { 0 });
		}
		void Build()
		{
			Title = "Server found:";
			WindowPosition = Gtk.WindowPosition.Center;
			BorderWidth = (uint)6;
			var vbox1 = new Gtk.VBox ();
			vbox1.Spacing = 6;

			vbox1.PackEnd(CmdLine(), false, false, 0);
			vbox1.Add(Listview());
			Add (vbox1);

			DeleteEvent += OnDeleteEvent;
			Child.ShowAll ();
			DefaultWidth = 400;
			DefaultHeight = 300;
		}
		Widget CmdLine()
		{
			btn_apply = new Gtk.Button ();
			btn_apply.Label = "Apply";
			btn_apply.Sensitive = false;
			var btn_cancel = new Gtk.Button ();
			btn_cancel.Label = "Cancel";

			var hbox = new Gtk.HBox ();
			hbox.Spacing = 6;
			hbox.PackEnd(btn_cancel, false, false, 0);
			hbox.PackEnd(btn_apply, false, false, 0);

			btn_cancel.Clicked += OnDeleteEvent;
			btn_apply.Clicked += HandleApplyClicked;

			return hbox;
		}

		void HandleApplyClicked (object sender, EventArgs e)
		{
			TreeIter itr;
			if( tview.Selection.GetSelected(out itr)){
				var p = lstore.GetValue(itr, 1).ToString();
				_main.SetPath(p);
				OnDeleteEvent(null, null);
			}
		}
		Widget Listview()
		{
			lstore = new ListStore(typeof(string), typeof(string));
			tview = new TreeView(lstore);
			var col = tview.AppendColumn ("Name", new CellRendererText (), "text", 0);
			col.Resizable = true;
			col.MinWidth = 100;
			tview.AppendColumn ("IP Address", new CellRendererText (), "text", 1);
			tview.Selection.Changed += delegate(object sender, EventArgs e) {
				btn_apply.Sensitive = tview.Selection.CountSelectedRows() == 1;
			};
			return tview;
		}

        public void DataReceived(object sender, DataReceivedEventArgs e)
        {
            var msg = (ResponseMessage)SerializerHelpers.Deserialize(e.Data, typeof(ResponseMessage));
//            Console.WriteLine(msg.Description + msg.IPAddress + msg.IPPort + msg.PathPrefix + " " + e.RemoteEndPoint.ToString());
			string remaddr = "http://" + msg.IPAddress + (msg.IPPort != 80 ? ":" + msg.IPPort : null) + '/'; 
			var itr = lstore.AppendValues(msg.Description, remaddr);
			if(tview.Selection.CountSelectedRows() == 0) tview.Selection.SelectIter(itr);
        }
		protected void OnDeleteEvent (object sender, EventArgs a)
		{
			uclient.Stop();
			Destroy();
			Dispose();
		}
	}
    public class ResponseMessage
    {
        public string PathPrefix { get; set; }
        public string Description { get; set; }
        public string IPAddress { get; set; }
        public int IPPort { get; set; }
    }
}

